/*
 * Copyright (c) 2006 Your Corporation. All Rights Reserved.
 */

package io.mft.redis.connection;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import cn.hutool.core.util.ObjectUtil;
import io.mft.redis.sentinel.ShardedJedisSentinelPool;
import lombok.extern.slf4j.Slf4j;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.Transaction;
import redis.clients.util.Pool;

/**
 * 描述:	 数据库连接管理
 * 版权:	 Copyright (c) 2005
 * 公司:	 思迪科技
 * 作者:	 易庆锋
 * 版本:	 1.0
 * 创建日期: 2006-10-4
 * 创建时间: 21:32:25
 */
@Slf4j
public final class RedisConnManager
{
	
	
	private static RedisConfigure configure = RedisConfigure.getInstance();
	
	/**
	 * 根据datasource.xml文件中配置的数据源ID，得到对应的数据库连接池中的连接
	 *
	 * @param id 数据源ID
	 * @return conn
	 */
	public static Object getConnection(String id)
	{
		Object dataSource = configure.getDataSource(id);
		if (dataSource != null)
		{
			if(dataSource instanceof Pool<?>)
			{
				Object conn = ((Pool<?>)dataSource).getResource();
				return conn;
			}
			if(dataSource instanceof JedisCluster)
			{
				return dataSource;
			}
		}
		return null;
	}
	
	/**
	 * 获得缺省的数据源连接池的数据库连接
	 *
	 * @return conn
	 */
	public static Object getConnection()
	{
		Object dataSource = configure.getDataSource();
		if (dataSource != null)
		{
			if(dataSource instanceof Pool<?>)
			{
				Object conn = ((Pool<?>)dataSource).getResource();
				return conn;
			}
			if(dataSource instanceof JedisCluster)
			{
				return dataSource;
			}
		}
		return null;
	}
	
	/**
	 * 开始数据库事务
	 * @param conn
	 */
	public static Transaction begin(Jedis conn)
	{
		if (conn != null && conn.isConnected())
		{
			return conn.multi();
		}
		return null;
	}
	
	/**
	 * 提交数据库事务
	 * @param conn
	 */
	public static void commit(Jedis conn, Transaction trans)
	{
		if (conn != null && conn.isConnected())
		{
			trans.exec();
		}
	}
	
	/**
	 * 回滚数据库事务
	 * @param conn
	 */
	public static void rollback(Jedis conn, Transaction trans)
	{
		if (conn != null && conn.isConnected())
		{
			trans.discard();
		}
	}
	
	/**
	 * 返回连接到连接池
	 */
	public static void returnJedis(Object conn, String id, boolean isSuccess)
	{
		Object dataSource = configure.getDataSource(id);
		if (dataSource != null)
		{
			if(dataSource instanceof JedisCluster)
			{
			}
			else if(dataSource instanceof Pool<?>)
			{
				if (isSuccess)
				{
					((Pool)dataSource).returnResource(conn);
				}
				else
				{
					((Pool)dataSource).returnBrokenResource(conn);
				}
			}
		} 
	}
	
	/**
	 * 关闭数据库连接(不使用连接池的时候在finally可以调用)
	 * @param conn
	 */
	public static void close(ShardedJedis conn)
	{
		if (conn != null)
		{
			conn.close();
		}
	}
	
	/**
	 * 
	 * 描述:获取所有连接
	 * 作者：刘宝
	 * 时间：2016-6-21 下午11:32:54
	 * @param id
	 * @return
	 */
	public static List<Jedis> getSingleConns(String id)
	{
		List<Jedis> jedisList = new ArrayList<Jedis>();
		Map<String, String> xmlMap = configure.getDbConnXmlMap(id);
		if (xmlMap != null)
		{
			String mode = (String) xmlMap.get("mode");
			if (ObjectUtil.isEmpty(mode))
			{
				mode = "0";
			}
			String password = (String) xmlMap.get("password");
			String timeout = (String) xmlMap.get("timeout");
			String url = (String) xmlMap.get("url");
			String[] urls = url.split("|");
			if (urls != null && urls.length > 0)
			{
			//	HashMap jedisHostMap = new HashMap();
				for (String u : urls)
				{
					String[] temp = u.split(":");
					String host = "";
					int port = 0;
					String master = "";
					if (temp != null && temp.length >= 2)
					{
						host = temp[0];
						port = Integer.valueOf(temp[1]);
						if (temp.length > 2)
						{
							master = temp[2];
						}
					}
					if (mode.equals("0") || mode.equals("1") || mode.equals("4"))
					{
						Jedis conn = null;
						try
						{
							JedisShardInfo shareInfo = new JedisShardInfo(host, port, Integer.valueOf(timeout));
							shareInfo.setPassword(password);
							conn = new Jedis(shareInfo);
							conn.connect();
							jedisList.add(conn);
						}
						catch (Exception e)
						{
							log.error("", e);
							try
							{
								if(conn != null)
								{
									conn.disconnect();
								}
							}
							catch (Exception e1)
							{
								log.error("", e1);
							}
						}
					}
					else if (mode.equals("2"))
					{
						Jedis conn = null;
						try
						{
							JedisShardInfo shareInfo = new JedisShardInfo(host, port, Integer.valueOf(timeout));
							conn = new Jedis(shareInfo);
							List<String> hostAndPort = conn.sentinelGetMasterAddrByName(master);
							conn.disconnect();
							if (hostAndPort != null && hostAndPort.size() >= 2)
							{
								host = hostAndPort.get(0);
								port = Integer.parseInt(hostAndPort.get(1));
								shareInfo = new JedisShardInfo(host, port, Integer.valueOf(timeout));
								shareInfo.setPassword(password);
								conn = new Jedis(shareInfo);
								conn.connect();
								jedisList.add(conn);
								break;
							}
						}
						catch (Exception e)
						{
							log.error("", e);
							try
							{
								if(conn != null)
								{
									conn.disconnect();
								}
							}
							catch (Exception e1)
							{
								log.error("", e1);
							}
						}
					}
					else if (mode.equals("3"))
					{
						try
						{
							ShardedJedisSentinelPool pool = (ShardedJedisSentinelPool)configure.getDataSource(id);
							List<HostAndPort> hostMaster = pool.getCurrentHostMaster();
							if(hostMaster != null && hostMaster.size() > 0)
							{
								for (Iterator<HostAndPort> iterator = hostMaster.iterator(); iterator.hasNext();)
								{
									HostAndPort hostAndPort = (HostAndPort) iterator.next();
									JedisShardInfo shareInfo = new JedisShardInfo(hostAndPort.getHost(), hostAndPort.getPort(), Integer.valueOf(timeout));
									shareInfo.setPassword(password);
									Jedis conn = null;
									try
									{
										conn = new Jedis(shareInfo);
										conn.connect();
										jedisList.add(conn);
									}
									catch (Exception e1)
									{
										log.error("", e1);
										try
										{
											if(conn != null)
											{
												conn.disconnect();
											}
										}
										catch (Exception e2)
										{
											log.error("", e2);
										}
									}
								}
							}
							break;
						}
						catch (Exception e)
						{
							log.error("", e);
						}
					}
				}
			}
			return jedisList;
		}
		return null;
	}
	
}
